/*
 * LegoBot v1.0-a
 * Copyright (c) 2010 MindstormsKid <mindstormskd@gmail.com>
 * Licensed under the MIT license <http://www.opensource.org/licenses/mit-license.php>
 *
 * LegoBot Core module <http://legocode.googlecode.com/svn/trunk/javascript/legobot/legobot.js>
 */
function LegoBot(s) {
	Object.merge(this, s);
}

Object.merge(LegoBot.prototype, {
	connected: false,
	
	connect: function(handle, start, stop){
		let that = this,
			instream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream),
			pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance(Components.interfaces.nsIInputStreamPump),
			transportservice = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService(Components.interfaces.nsISocketTransportService),
			transport = transportservice.createTransport(null, 0, this.host, this.port, null),
			outstream = this._outstream = transport.openOutputStream(0, 0, 0),
			stream = transport.openInputStream(0, 0, 0);
		
		instream.init(stream);
		pump.init(stream, -1, -1, 0, 0, false);
		pump.asyncRead({
			onStartRequest: function(request, context){
				that.connected = true;
				that.trigger("LegoBot.connect");
				start && start(request, context);
			},
			onStopRequest: function(request, context, status){
				outstream.close();
				instream.close();
				that.connected = false;
				that.trigger("LegoBot.disconnect");
				stop && stop(request, context, status);
			},
			onDataAvailable: function(request, context, inputStream, offset, count){
				let msg = instream.read(count);
				that.trigger("LegoBot.receive", msg);
				handle && handle(msg, request, context, inputStream, offset, count);
				that.write(msg, true);
			}
		}, null);
		
		return this;
	},
	send: function(msg){
		this.error("LegoBot is not connected!", "core", this.connected === true);
		
		msg = msg.template(this.var);
		this._outstream.write(msg + "\n", (msg + "\n").length);
		return this.write(msg);
	},
	error: function(msg, module, test){
		if (typeof test === "boolean") {
			if (test === true) {
				return;
			} else {
				throw this.error(msg, module);
			}
		} else {
			let e = {
				fileName: "legobot." + module,
				name: "LegoBot error",
				message: msg
			};
			this.trigger("LegoBot.error", e);
			return e;
		}
	},
	"var": function(o){
		Object.merge(this.var, o);
		return this;
	},
	trigger: function(name, data){
		let arr = (this.trigger[name] = this.trigger[name] || []);
		if (typeof data == "function") {
			arr.push(data);
		} else if (arr) {
			arr.each(function(func){ func(data); });
		}
		return this;
	},
	write: function(msg, out){
		this.print(Date.now() + (out ? ">>> " : "<<< ") + msg);
		return this;
	}
});